package com.lixh.sdk.base.literoute

import android.content.Context
import androidx.fragment.app.Fragment
import com.lixh.sdk.base.http.RouterService
import java.lang.reflect.Method
import java.lang.reflect.Proxy

/**
 * LiteRouter for Android
 *
 * @author wan7451
 */
class LiteRouter private constructor(builder: Builder) {
    private val interceptors: MutableList<Interceptor> = builder.interceptors


    /**
     * create router class service
     *
     * @param service router class
     * @param context from context
     * @param <T> classtype
     * @return class
    </T> */
    fun <T> create(service: Class<T>): T {
        return Proxy.newProxyInstance(
            service.classLoader, arrayOf<Class<*>>(service)
        ) { proxy, method, args ->
            val interceptor = interceptors.listIterator()
            var wrapper = IntentWrapper()
            while (interceptor.hasNext()) {
                interceptor.next().intercept(proxy, method, args, wrapper)
                    .also { wrapper = it }
            }
            parseReturnType(wrapper, method, args)
        } as T
    }

    private fun parseReturnType(
        wrapper: IntentWrapper,
        method: Method,
        args: Array<out Any>?,
    ): Any? {
        when (method.returnType) {
            //利用 IntentWrapper 包装下 方便其它 调用
            IntentWrapper::class.java -> {
                return wrapper
            }
            //利用 IntentWrapper 包装下 方便其它 调用
            Fragment::class.java -> {
                wrapper.fragment?.arguments = wrapper.extras;
                return wrapper.fragment
            }
            Void.TYPE -> {
                args?.let { arg ->
                    val context: Context = (arg.find { it is Context }
                        ?: throw RuntimeException("method return type is void,must arg need content")) as Context
                    wrapper.go(context)
                }

                return null
            }
            else -> {
                throw RuntimeException("method return type only support 'void' or 'IntentWrapper'")
            }
        }
    }

    class Builder {
        val interceptors: MutableList<Interceptor> = mutableListOf(DefaultInterceptor())

        fun addInterceptor(interceptor: Interceptor) = apply {
            interceptors += interceptor
        }

        fun build(): LiteRouter {
            return LiteRouter(this)
        }
    }
}

inline fun <reified T : RouterService> createRouterService(): T {
    return LiteRouter.Builder().build().create(T::class.java)
}